﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using D2D = Microsoft.WindowsAPICodePack.DirectX.Direct2D1;
using DI = Microsoft.WindowsAPICodePack.DirectX.WindowsImagingComponent;
using DW = Microsoft.WindowsAPICodePack.DirectX.DirectWrite;
using Paint = System.Drawing;

namespace Framework
{
    public class Base
    {
        #region Dependency

        public static object Unset = new object();

        // Type -> Property -> PropertyType * DefaultValue
        public static Dictionary<string, Dictionary<string, Tuple<Type, object>>> Meta = new Dictionary<string, Dictionary<string, Tuple<Type, object>>>();

        public Dictionary<string, object> Dict = new Dictionary<string, object>();

        public static void RegisterType(Type self)
        {
            if (!Meta.ContainsKey(self.Name))
                Meta.Add(self.Name, new Dictionary<string, Tuple<Type, object>>());
        }

        public static void RegisterType(Type self, Type parent)
        {
            if (!Meta.ContainsKey(self.Name))
                Meta.Add(self.Name, new Dictionary<string, Tuple<Type, object>>());

            foreach (var prop in Meta[parent.Name])
            {
                Meta[self.Name].Add(prop.Key, prop.Value);
            }
        }

        public static void RegisterProp(Type type, string prop, Type ty, object value)
        {
            Meta[type.Name][prop] = new Tuple<Type, object>(ty, value);
        }

        public void RegisterProp(string prop, Type ty, object value)
        {
            Meta[this.GetType().Name][prop] = new Tuple<Type, object>(ty, value);
        }

        public object GetProp(string name)
        {
            if (Dict.ContainsKey(name))
                return Dict[name];
            else 
            {
                if (name.Contains('|'))
                {
                    var names = name.Split('|');
                    return Meta[names[0]][names[1]].Item2;
                }
                else
                    return Meta[this.GetType().Name][name].Item2;
            
            }
                
        }

        public object GetLocalProp(string name)
        {
            if (Dict.ContainsKey(name))
                return Dict[name];
            else
                return Unset;
        }

        public void SetProp(string name, object value)
        {
            Dict[name] = value;
        }
        #endregion 
        
        public object GetField(string field) 
        {
            return GetType().GetField(field).GetValue(this);
        }

        public void SetField(string field,object value) 
        {
            GetType().GetField(field).SetValue(this,value);
        }

        public virtual void LoadJson(JObject json) 
        {
            //string a = "";
            
        }

        public virtual JObject ToJson()
        {
            var result = new JObject();
            foreach (var i in Dict)
            {
                if (i is Base)
                    result.Add(i.Key, ((Base)(i.Value)).ToJson());
                else
                    result.Add(i.Key, JsonConvert.SerializeObject(i.Value));
            }
            return result;
        }
    }

    [Map("PresentationFrameworkCollection")]
    public class Collection<T> : List<T>
    { }

    public class DrawingContext
    {
        public static DrawingContext Main;

        public D2D.D2DFactory rendering;
        public DI.ImagingFactory imaging;
        public DW.DWriteFactory writing;
        public D2D.RenderTarget target;
    }


}
